package frequency

import (
	"fmt"
	"github.com/pkg/errors"
	"talent.com/server/durotar.git/tools/tz"
)

// Local Memory实现
// 实现方式：使用全局Map容器记录每次请求的时间时间点，并统计次数。采用被动清除过期办法（下次请求时计算时间点是否过期）
// 并重新下一个周期的计算
// 虽然有被动过期机制，消耗内存跟当前活跃用户成正比，可以设置一个全局时钟且秋清除非活跃用户占用的内存。

type MemoryLimiter struct {
	// 限流配置
	rules map[string]LimiterRule
	// 全局计数容器
	globalCounter map[string]*counterEntry
}

type counterEntry struct {
	ts    int64
	count uint
}

func (l *MemoryLimiter) RegisterRules(rules map[string]LimiterRule) error {
	l.rules = rules
	l.globalCounter = make(map[string]*counterEntry, 2000)
	return nil
}

func (l *MemoryLimiter) Check(ruleCode string, key interface{}) (bool, error) {
	var (
		//rule LimiterRule
		gKey = fmt.Sprintf("%v-%v", ruleCode, key)
	)

	if rule, ok := l.rules[ruleCode]; !ok {
		return false, errors.Errorf("the ruleCode is not exists: [%v]", ruleCode)
	} else {
		if entry, ok := l.globalCounter[gKey]; ok {
			now := tz.GetNowTs()
			if now-entry.ts >= rule.Period {
				entry.ts = now
				entry.count = 1
				return true, nil
			} else {
				entry.count += 1
				if entry.count > rule.Count {
					return false, nil
				} else {
					return true, nil
				}
			}
		} else {
			l.globalCounter[gKey] = &counterEntry{
				ts:    tz.GetNowTs(),
				count: 1,
			}
			return true, nil
		}
	}
}
